package com.tarena.demo.luban.all.main.consumer;

import com.tarena.demo.luban.all.main.service.OrderService;
import com.tarena.demo.luban.commons.exception.BusinessDemoException;
import com.tarena.demo.luban.commons.restful.ResponseCode;
import com.tarena.demo.luban.protocol.order.param.OrderAddParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@RocketMQMessageListener(
        topic = "order_add_topic",
        consumerGroup = "order-add-consumer-group")
public class OrderAddConsumer01 implements RocketMQListener<OrderAddParam> {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public void onMessage(OrderAddParam message) {
        //第一步 生成一个key值 value值随机数
        String lock="order:add:lock:"+message.getOrderSn();
        String randCode=new Random().nextInt(9000)+1000+"";
        //第二步 抢锁 设置超时时间 setnx+expire
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        //setnx lock randCode EX 8
        Boolean tryLock =
                opsForValue.setIfAbsent(lock, randCode, 8, TimeUnit.SECONDS);
        try{
            int count=0;
            while(!tryLock){
                //第四步 睡5秒 重新抢
                long sleepTime=(5000-count*2000)<0?0:(5000-count*2000);
                Thread.sleep(sleepTime);
                tryLock=opsForValue.setIfAbsent(lock, randCode, 8, TimeUnit.SECONDS);
                if (!tryLock&&count==2){
                    //抢第四次没抢到的时候，别再循环了，直接结束
                    return;
                }
                count++;
            }
            //第三步执行业务逻辑
            orderService.addOrder(message);
        }catch(BusinessDemoException e){
            log.error("当前新增订单 出现业务异常：{}",e.getMessage());
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            //第五步 读取锁的value值
            String lockValue = opsForValue.get(lock);
            //判断 满足释放要求
            if (StringUtils.isNotEmpty(lockValue)&&lockValue.equals(randCode)){
                //第六步 手动释放
                redisTemplate.delete(lock);
            }
        }
    }
}
